using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using RBAC.Domain.Dto.Output;
using RBAC.ErrorCode;
using RBAC.Read.Api.Application.Command.Permission;
using RBAC.Read.Api.Application.Command.Role;
using RBAC.Read.Api.Application.Command.User;
using RBAC.Read.Api.Application.Command.User.Login;
using RBAC.Interstructrue.Base;
using MySql.Data.MySqlClient;
using Dapper;
using Microsoft.Extensions.Configuration;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authorization;

namespace RBAC.Read.Api.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    [Authorize]
    public class RBACController : ControllerBase
    {
        private readonly IMediator mediator;
        private readonly IDbConnectionFactory _connectionFactory;
        private readonly IConfiguration _configuration;

        public RBACController(IMediator mediator, IDbConnectionFactory connectionFactory, IConfiguration configuration)
        {
            this.mediator = mediator;
            this._connectionFactory = connectionFactory;
            this._configuration = configuration;
        }
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public async Task<APIResult<UserDto>> Login([FromQuery] LoginCommand request)
        {
            // 调用原有逻辑获取用户信息
            var result = await mediator.Send(request);

            // 登录成功则基于用户信息签发JWT
            if (result != null && result.Code == APIEnums.Success && result.Data != null)
            {
                var key = _configuration["Jwt:Key"] ?? "SuperSecretKey_ForDemoOnly_ChangeMe";
                var issuer = _configuration["Jwt:Issuer"] ?? "RBAC.Read.Api";
                var audience = _configuration["Jwt:Audience"] ?? "RBAC.Read.Api.Client";
                var expireMinutesStr = _configuration["Jwt:ExpireMinutes"];
                var expireMinutes = 120;
                if (int.TryParse(expireMinutesStr, out var parsed))
                {
                    expireMinutes = parsed;
                }

                var claims = new[]
                {
                    new Claim(JwtRegisteredClaimNames.Sub, result.Data.Id.ToString()),
                    new Claim("userId", result.Data.Id.ToString()),
                    new Claim("userName", result.Data.UserName ?? string.Empty),
                    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
                };

                var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
                var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

                var tokenDescriptor = new JwtSecurityToken(
                    issuer: issuer,
                    audience: audience,
                    claims: claims,
                    expires: DateTime.UtcNow.AddMinutes(expireMinutes),
                    signingCredentials: credentials
                );

                var token = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);
                result.Data.Token = token;
            }

            return result;
        }

        /// <summary>
        /// 获取权限列表
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        public Task<APIResult<List<GetPermissionListDto>>> GetPermission([FromQuery]GetPermissionCommand request, CancellationToken cancellationToken)
        {
            return mediator.Send(request);
        }
        /// <summary>
        /// 获取权限列表
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        public Task<APIPaging<PermissionDto>> GetPermissionList([FromQuery]GetPermissionListCommand request)
        {
            return mediator.Send(request);
        }
        /// <summary>
        /// 获取角色列表
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        public Task<APIPaging<GetRoleListDto>> GetRoleList([FromQuery]GetRoleListCommand request)
        {
            return mediator.Send(request);
        }
        /// <summary>
        /// 获取用户列表
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        public Task<APIPaging<GetUserListDto>> GetUserList([FromQuery]GetUserListCommand request)
        {
            return mediator.Send(request);
        }

        /// <summary>
        /// 测试数据库连接
        /// </summary>
        /// <returns></returns>
        [HttpGet("test-connection")]
        public async Task<IActionResult> TestConnection()
        {
            try
            {
                using var connection = _connectionFactory.CreateConnectionWithRetry();
                var result = await connection.QueryFirstOrDefaultAsync<string>("SELECT 'Connection successful' as status");
                
                // 将IDbConnection强制转换为MySqlConnection以访问DataSource和Database属性
                var mySqlConnection = connection as MySql.Data.MySqlClient.MySqlConnection;
                
                return Ok(new { 
                    success = true, 
                    message = "数据库连接成功", 
                    timestamp = DateTime.Now,
                    server = mySqlConnection?.DataSource ?? "Unknown",
                    database = mySqlConnection?.Database ?? "Unknown"
                });
            }
            catch (MySql.Data.MySqlClient.MySqlException ex)
            {
                return StatusCode(500, new { 
                    success = false, 
                    message = "MySQL连接失败", 
                    error = ex.Message,
                    errorCode = ex.Number,
                    timestamp = DateTime.Now
                });
            }
            catch (Exception ex)
            {
                return StatusCode(500, new { 
                    success = false, 
                    message = "连接测试失败", 
                    error = ex.Message,
                    timestamp = DateTime.Now
                });
            }
        }
    }
}
